// ===================================
// <copyright>
// This file is part of LABSMFController.
//
//    LABSMFController is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    LABSMFController is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with LABSMFController.  If not, see <http://www.gnu.org/licenses/>.
//    Copyright 2011 David Bakker
//
//</copyright>
// <author>David Bakker</author>
// <email>mailto:DavidFBakker@gmail.com</email>
// <created>Saturday, May 21, 2011</created>
// <lastedit>Saturday, May 21, 2011</lastedit>
// ===================================

using System.Threading;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
using LABSMFController.LABS.Classses;
using LABSMFController.LABS.Devices;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;

namespace LABSMFController.LABS.Devices
{


    public class PWMValveDevice
    {
        public PWMValveDevice(string description, FEZ_Pin.Digital digitalPulsePin, AnalogIn.Pin analogFeedBackPin, double voltageStep, double voltage0Angle)
        {
            AnalogFeedBack = new AnalogIn(analogFeedBackPin);
            AnalogFeedBack.SetLinearScale(0, 3300);

            VoltageStep = voltageStep;
            Voltage0Angle = voltage0Angle;

            Deviation = VoltageStep/4;

            HighMAXPulse = 2.930*1000*1000;
            LowMAXPulse = .59*1000*1000;
            PulseLow = 1*1000*1000;

            Description = description;
            DigitalPulsePin = (Cpu.Pin) digitalPulsePin;
            AnalogFeedBackPin = analogFeedBackPin;

            DigitalOutPutCompare= new OutputCompare(DigitalPulsePin, false, 2);

            CurrentAngle = GetAngle();
            IsRunning = false;

            Header = "Description,CurrentAngle,IsRunning";
        }

        internal OutputCompare DigitalOutPutCompare { get; set; }

        private double HighMAXPulse { get; set; }
        private double LowMAXPulse { get; set; }
        private uint PulseLow { get; set; }

        private double VoltageStep { get; set; }
        private double Voltage0Angle { get; set; }
        private double Deviation { get; set; }

        internal Cpu.Pin DigitalPulsePin { get; set; }
        internal AnalogIn.Pin AnalogFeedBackPin { get; set; }
        private AnalogIn AnalogFeedBack { get; set; }

        public string Description { get; private set; }


        public double CurrentAngle { get; set; }

        public bool IsRunning { get; set; }

        internal string Header { get; set; }

        public string GetClientOutPut()
        {
            string ret = Description + "," + CurrentAngle + "," + IsRunning + ";";
            return ret;
        }

        internal int GetAngle()
        {
            return (int) ((GetVolts() - Voltage0Angle)/VoltageStep);
        }


        public int GetAngleFromVolts(double volts)
        {
            return (int) ((volts - Voltage0Angle)/VoltageStep);
        }

        public double GetVolts()
        {
            const int max = 12;
            double input = 0;

            for (int c = 0; c < max; c++)
            {
                input += AnalogFeedBack.Read();
            }

            const double ret = 0;

            if (input > 0)
            {
                return input/1000/max;
            }

            return ret;
        }

        public uint[] GetTimings(double angle)
        {
            var ret = new uint[2];

            var pos = (uint) (((float) ((HighMAXPulse - LowMAXPulse)/90)*(angle)) + LowMAXPulse);
            ret[0] = pos;
            ret[1] = PulseLow;

            return ret;
        }


        public double GetVoltageFromAngle(double angle)
        {
            return VoltageStep*angle + Voltage0Angle;
        }


        internal bool CheckAngle(double startAngle, double angle)
        {
            double gv = GetVolts();

            CurrentAngle = GetAngleFromVolts(gv);

            double st = GetVoltageFromAngle(startAngle);
            double an = GetVoltageFromAngle(angle);

            if (st > an)
            {
                if ((gv - Deviation) < an)
                    return true;
            }
            else
            {
                if ((gv + Deviation) > an)
                    return true;
            }
            return false;
        }
    }
}
